不同数据类型的遍历方式
-
数组/切片:
|
|
for index, value := range arr { // index 是下标,value 是元素值 // &v 始终指向同一个地址 } |
-
map:
|
|
for key, value := range m { // key 是键,value 是值 // &v 始终指向同一个地址 } |
-
字符串:
|
|
for index, runeValue := range s { // index 是字节位置,runeValue 是 Unicode 字符 } |
-
channel:
|
|
for value := range ch { // 从 channel 接收值,直到 channel 关闭 } |
range 遍历时返回的是元素的拷贝,不是原始元素的引用
for-range切片时候可以边遍历边append吗?
当遍历切片时候,可以边遍历边append操作,这并不会造成死循环。因为遍历之前已经确定了循环范围,遍历操作相当如下伪代码:
|
|
len_temp := len(range) // 循环上界 range_temp := range for index_temp = 0; index_temp < len_temp; index_temp++ { value_temp = range_temp[index_temp] index = index_temp value = value_temp original body } |
无论遍历数组还是切片,返回都是数组或切片中的值拷贝,所以修改v的值,最后都无效,使用item[i]或者指针这种方式才有效。
for-range映射时候可以边遍历,边新增或删除吗?
若在一个Goroutine里面边遍历边新增、删除,理论上是可以的,不会触发写检测的,新增的key-value可能会被访问到,也可能不会。
若多个Goroutine中进行遍历、新增、删除操作的话,是不可以的,是可能触发写检测的,然后直接panic。
map 的range 同切片,但是有一些特殊如下:
可以修改值,但不能修改 map 的结构(增删键),这是 Go map 遍历时最重要的规则。
-
允许的操作:
-
修改现有键对应的值(包括通过指针修改结构体字段)
-
修改值内部的字段(如果值是可变的)
-
禁止的操作:
| map 的值类型 |
v 的性质 |
能否影响原 map |
示例 |
int, string, struct(值类型) |
值的拷贝 |
❌ 不能 |
v = newVal 无效 |
*struct, slice, map(引用类型) |
指针/引用的拷贝 |
✅ 能 |
v.Field = newVal 有效 |
原因:虽然 v 本身是拷贝的指针,但它指向的是同一块内存。
「三年博客,如果觉得我的文章对您有用,请帮助本站成长」
共有 0 - golang for range 遍历